home *** CD-ROM | disk | FTP | other *** search
/ Aminet 28 / Aminet 28 (1998)(GTI - Schatztruhe)[!][Dec 1998].iso / Aminet / dev / c / qtools0.2-src.lha / src / libqtools / graphics.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-07-15  |  17.8 KB  |  660 lines

  1. #define    LIBQTOOLS_CORE
  2. #include "../include/libqtools.h"
  3. #if defined(HAVE_LIBPNG) && defined(HAVE_PNG_H)
  4. # include <png.h>
  5. #endif
  6. #if defined(HAVE_LIBJPEG) && defined(HAVE_JPEGLIB_H)
  7. # include <jpeglib.h>
  8. #endif
  9.  
  10. bool dither = FALSE;
  11. short int dithervalue = 16;
  12. bool smoothing = FALSE;
  13. short int smoothingvalue = 2;
  14. short int smoothingshift = 1;
  15.  
  16. /*#define FS_SCALE 16 */
  17. #define FS_SCALE dithervalue
  18. /*#define S_SCALE 2 */
  19. #define S_SCALE smoothingvalue
  20. /*#define S_SHIFT 2 */
  21. #define S_SHIFT smoothingshift
  22.  
  23. typedef float PRECISION;
  24. typedef float PRECISION_EXT;
  25.  
  26. struct drgb {
  27.   PRECISION r, g, b;
  28. };
  29.  
  30. static inline unsigned char MatchD(register struct drgb *rawpix, register struct rgb *Palette)
  31. {
  32.   struct rgb newpix;
  33.  
  34.   newpix.r = (unsigned char)rawpix->r;
  35.   newpix.g = (unsigned char)rawpix->g;
  36.   newpix.b = (unsigned char)rawpix->b;
  37.   return Match(&newpix, Palette);
  38. }
  39.  
  40. /*
  41.  * picture-tools
  42.  */
  43.  
  44. bool RemapPalettes(unsigned char *dataBody, int dataSize, struct rgb * oldPalette, struct rgb * newPalette)
  45. {
  46.   unsigned char *conversionArray;
  47.  
  48.   if ((conversionArray = (unsigned char *)tmalloc(256))) {
  49.     int i;
  50.  
  51.     for (i = 0; i < 256; i++)
  52.       conversionArray[i] = Match(&oldPalette[i], &newPalette[i]);
  53.     for (i = 0; i < dataSize; i++)
  54.       dataBody[i] = conversionArray[dataBody[i]];
  55.  
  56.     tfree(conversionArray);
  57.     return TRUE;
  58.   }
  59.   else
  60.     return FALSE;
  61. }
  62.  
  63. #ifdef HAVE_LIBPNG
  64. #ifdef REPLACE_STDIO
  65. void png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
  66. {
  67.   if (__fread(data, (png_size_t) 1, length, (FILE *) png_ptr->io_ptr) != length)
  68.     png_error(png_ptr, "Read Error");
  69. }
  70.  
  71. void png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
  72. {
  73.   if (__fwrite(data, 1, length, (FILE *) (png_ptr->io_ptr)) != length)
  74.     png_error(png_ptr, "Write Error");
  75. }
  76. #endif
  77.  
  78. bool SavePNG(register FILE * imgFile, register struct palpic *Picture)
  79. {
  80.   png_struct *png_ptr;
  81.   png_info *info_ptr;
  82.   bool retval = FALSE;
  83.  
  84.   if ((png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0))) {
  85.     if ((info_ptr = png_create_info_struct(png_ptr))) {
  86.       if (!setjmp(png_ptr->jmpbuf)) {
  87.     short int y;
  88.     png_byte *row_pointers = (png_byte *) Picture->rawdata;
  89.  
  90.     png_init_io(png_ptr, imgFile);
  91.     png_set_IHDR(png_ptr, info_ptr, Picture->width, Picture->height, 8, PNG_COLOR_TYPE_PALETTE,
  92.      PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
  93.     png_set_PLTE(png_ptr, info_ptr, (png_color *) Picture->palette, 256);
  94.     png_set_compression_level(png_ptr, 9);
  95.     png_write_info(png_ptr, info_ptr);
  96.     png_set_packing(png_ptr);
  97.     for (y = 0; y < Picture->height; y++) {
  98.       png_write_rows(png_ptr, &row_pointers, 1);
  99.       row_pointers += Picture->width;
  100.     }
  101.     png_write_end(png_ptr, info_ptr);
  102.     retval = TRUE;
  103.       }
  104.       else
  105.     eprintf("cannot set png-jump\n");
  106.     }
  107.     else
  108.       eprintf("cannot create info-struct\n");
  109.  
  110.     png_destroy_write_struct(&png_ptr, 0);
  111.   }
  112.   else
  113.     eprintf("cannot create png-struct\n");
  114.  
  115.   return retval;
  116. }
  117. #endif
  118. #ifdef HAVE_LIBJPEG
  119. bool SaveJPEG(register FILE * imgFile, register unsigned char *rawBody, register short int width, register short int height)
  120. {
  121.   struct jpeg_compress_struct cinfo;
  122.   struct jpeg_error_mgr jerr;
  123.   unsigned char *row_pointers = rawBody;
  124.  
  125.   cinfo.err = jpeg_std_error(&jerr);
  126.   jpeg_create_compress(&cinfo);
  127.   jpeg_stdio_dest(&cinfo, imgFile);
  128.  
  129.   cinfo.image_width = width;                    /* image width and height, in pixels */
  130.   cinfo.image_height = height;
  131.   cinfo.input_components = 3;                    /* # of color components per pixel */
  132.   cinfo.in_color_space = JCS_RGB;                /* colorspace of input image */
  133.  
  134.   jpeg_set_defaults(&cinfo);
  135.  
  136.   cinfo.dct_method = JDCT_FLOAT;
  137.   cinfo.optimize_coding = TRUE;
  138.  
  139.   jpeg_set_quality(&cinfo, 100, TRUE);
  140.   jpeg_start_compress(&cinfo, TRUE);
  141.   while (cinfo.next_scanline < cinfo.image_height) {
  142.     jpeg_write_scanlines(&cinfo, &row_pointers, 1);
  143.     row_pointers += (width * 3);
  144.   }
  145.  
  146.   jpeg_finish_compress(&cinfo);
  147.   jpeg_destroy_compress(&cinfo);
  148.  
  149.   return TRUE;
  150. }
  151. #endif
  152.  
  153. bool PutImage(FILE * file, struct palpic * Picture, filetype picType)
  154. {
  155.   bool retval = FALSE;
  156.  
  157.   switch (picType) {
  158.     case TYPE_PPM:
  159. #ifdef HAVE_LIBJPEG
  160.     case TYPE_JPEG:
  161. #endif
  162.       {
  163.     short int x = Picture->width, y = Picture->height;
  164.     struct rgb *PPMPic = (struct rgb *)tmalloc(x * y * 3);
  165.  
  166.     if (PPMPic) {
  167.       unsigned char *bodySrc = Picture->rawdata;
  168.       struct rgb *bodyPal = Picture->palette;
  169.       struct rgb *bodyDst = PPMPic;
  170.  
  171.       /* convert body */
  172.       for (y = 0; y < Picture->width; y++) {
  173.         for (x = 0; x < Picture->height; x++) {
  174.           *bodyDst++ = bodyPal[(short int)(*bodySrc++)];
  175.         }
  176.       }
  177.  
  178.       if (picType == TYPE_PPM) {
  179.         /* put header */
  180.         fprintf(file, "P6\n%d %d\n255\n", Picture->width, Picture->height);
  181.         fflush(file);
  182.         /* put body */
  183.         __write(fileno(file), PPMPic, (Picture->width * Picture->height * 3));
  184.         retval = TRUE;
  185.       }
  186. #ifdef HAVE_LIBJPEG
  187.       else
  188.         retval = SaveJPEG(file, (unsigned char *)PPMPic, Picture->width, Picture->height);
  189. #endif
  190.       tfree(PPMPic);
  191.     }
  192.     else
  193.       eprintf(failed_memory, x * y * 3, "ppm-body");
  194.       }
  195.       break;
  196. #ifdef HAVE_LIBPNG
  197.     case TYPE_PNG:
  198.       retval = SavePNG(file, Picture);
  199.       break;
  200. #endif
  201.     default:
  202.       eprintf("unknown picture-type\n");
  203.       break;
  204.   }
  205.  
  206.   return retval;
  207. }
  208.  
  209. #define CHECK_SIZE    12
  210.  
  211. filetype CheckImage(register FILE * imgFile)
  212. {
  213.   union blabla {
  214.     char minChars[CHECK_SIZE];
  215.     int minInts[CHECK_SIZE / 4];
  216.   } minHeader;
  217.  
  218.   __fseek(imgFile, 0, SEEK_SET);
  219.   __fread(&minHeader, 1, CHECK_SIZE, imgFile);
  220.   __fseek(imgFile, 0, SEEK_SET);
  221. #ifdef HAVE_LIBPNG
  222.   if ((minHeader.minInts[0] == 0x89504E47) && (minHeader.minInts[1] == 0x0D0A1A0A))
  223.     return TYPE_PNG;
  224. #endif
  225. #ifdef HAVE_LIBJPEG
  226.   if ((minHeader.minInts[0] == 0xFFD8FFE0) && (minHeader.minInts[1] == 0x00104A46))
  227.     return TYPE_JPEG;
  228. #endif
  229. #ifdef ILBM
  230.   if (minHeader.minInts[0] == 0x464F524D)
  231.     &&(minHeader.minInts[2] == 0x494C424D))
  232.       return TYPE_ILBM;
  233. #endif
  234.   if ((minHeader.minChars[0] == 'P') && (minHeader.minChars[1] == '6') && (minHeader.minChars[2] == '\n'))
  235.     return TYPE_PPM;
  236.   if ((minHeader.minChars[0] == 'P') && (minHeader.minChars[1] == '5') && (minHeader.minChars[2] == '\n'))
  237.     return TYPE_PGM;
  238.  
  239.   return TYPE_NONE;
  240. }
  241.  
  242. #ifdef HAVE_LIBPNG
  243. filetype LoadPNG(register FILE * imgFile, register struct rgb ** bodySrc, register short int *width, register short int *height) {
  244.   png_struct *png_ptr;
  245.   png_info *info_ptr;
  246.   short int color_type = 0;
  247.  
  248.   if ((png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0))) {
  249.     if ((info_ptr = png_create_info_struct(png_ptr))) {
  250.       if (!setjmp(png_ptr->jmpbuf)) {
  251.     short int number_passes, pass, y;
  252.  
  253.     png_init_io(png_ptr, imgFile);
  254.     png_read_info(png_ptr, info_ptr);
  255.  
  256.     *width = info_ptr->width;
  257.     *height = info_ptr->height;
  258.     color_type = info_ptr->color_type;
  259.  
  260.     if ((*bodySrc = (struct rgb *)tmalloc((*width) * (*height) * 3))) {
  261.       png_byte *row_pointers = (png_byte *) (*bodySrc);
  262.  
  263.       if ((color_type == PNG_COLOR_TYPE_PALETTE) || ((color_type == PNG_COLOR_TYPE_GRAY) && (info_ptr->bit_depth < 8)))
  264.         png_set_expand(png_ptr);
  265.  
  266.       number_passes = png_set_interlace_handling(png_ptr);
  267.       png_read_update_info(png_ptr, info_ptr);
  268.       for (pass = 0; pass < number_passes; pass++) {
  269.         for (y = 0; y < (*height); y++) {
  270.           png_read_rows(png_ptr, &row_pointers, 0, 1);
  271.           if (color_type == PNG_COLOR_TYPE_GRAY)
  272.         row_pointers += ((*width));
  273.           else
  274.         row_pointers += ((*width) * 3);
  275.         }
  276.       }
  277.     }
  278.     else
  279.       eprintf(failed_memory, (*width) * (*height) * 3, "picture");
  280.  
  281.     png_read_end(png_ptr, info_ptr);
  282.       }
  283.       else
  284.     eprintf("cannot set png-jump\n");
  285.  
  286.       png_destroy_read_struct(&png_ptr, &info_ptr, 0);
  287.     }
  288.     else {
  289.       png_destroy_read_struct(&png_ptr, 0, 0);
  290.       eprintf("cannot create info-struct\n");
  291.     }
  292.   }
  293.   else
  294.     eprintf("cannot create png-struct\n");
  295.  
  296.   if (color_type == PNG_COLOR_TYPE_GRAY)
  297.     return TYPE_PGM;
  298.   else if (color_type)
  299.     return TYPE_PPM;
  300.   else
  301.     return TYPE_NONE;
  302. }
  303. #endif
  304. #ifdef HAVE_LIBJPEG
  305. filetype LoadJPEG(register FILE * imgFile, register struct rgb ** bodySrc, register short int *width, register short int *height) {
  306.   struct jpeg_decompress_struct cinfo;
  307.   struct jpeg_error_mgr jerr;
  308.  
  309.   cinfo.err = jpeg_std_error(&jerr);
  310.   jpeg_create_decompress(&cinfo);
  311.   jpeg_stdio_src(&cinfo, imgFile);
  312.   jpeg_read_header(&cinfo, TRUE);
  313.  
  314.   cinfo.dct_method = JDCT_FLOAT;
  315.   cinfo.out_color_space = JCS_RGB;
  316.  
  317.   jpeg_start_decompress(&cinfo);
  318.  
  319.   *width = (short int)cinfo.image_width;
  320.   *height = (short int)cinfo.image_height;
  321.  
  322.   if ((*bodySrc = (struct rgb *)tmalloc(cinfo.image_width * cinfo.image_height * 3))) {
  323.     unsigned char *row_pointers = (unsigned char *)(*bodySrc);
  324.  
  325.     while (cinfo.output_scanline < cinfo.output_height) {
  326.       jpeg_read_scanlines(&cinfo, &row_pointers, 1);
  327.       row_pointers += (cinfo.image_width * 3);
  328.     }
  329.   }
  330.   else
  331.     eprintf(failed_memory, cinfo.image_width * cinfo.image_height * 3, "picture");
  332.  
  333.   jpeg_finish_decompress(&cinfo);
  334.   jpeg_destroy_decompress(&cinfo);
  335.  
  336.   return TYPE_PPM;
  337. }
  338. #endif
  339.  
  340. struct rgb *LoadImage(register FILE * imgFile, register filetype * picType, register short int *width, register short int *height) {
  341.   struct rgb *bodySrc = 0;
  342.   int x, y, reead;
  343.  
  344.   switch (*picType) {
  345. #ifdef HAVE_LIBPNG
  346.     case TYPE_PNG:
  347.       *picType = LoadPNG(imgFile, (struct rgb **)&bodySrc, width, height);
  348.       break;
  349. #endif
  350. #ifdef HAVE_LIBJPEG
  351.     case TYPE_JPEG:
  352.       *picType = LoadJPEG(imgFile, (struct rgb **)&bodySrc, width, height);
  353.       break;
  354. #endif
  355. #ifdef ILBM
  356.     case TYPE_ILBM:
  357.       break;
  358. #endif
  359.     case TYPE_PPM:
  360.       fscanf(imgFile, "%nP6\n%d %d\n255\n", &reead, &x, &y);
  361.       *width = (short int)x;
  362.       *height = (short int)y;
  363.       if ((bodySrc = (struct rgb *)tmalloc(x * y * 3))) {
  364.         __lseek(fileno(imgFile), reead, SEEK_SET);
  365.     __read(fileno(imgFile), bodySrc, x * y * 3);
  366.       }
  367.       else
  368.     eprintf(failed_memory, x * y * 3, "picture");
  369.       break;
  370.     case TYPE_PGM:
  371.       fscanf(imgFile, "%nP5\n%d %d\n255\n", &reead, &x, &y);
  372.       *width = (short int)x;
  373.       *height = (short int)y;
  374.       if ((bodySrc = (struct rgb *)tmalloc(x * y))) {
  375.         __lseek(fileno(imgFile), reead, SEEK_SET);
  376.     __read(fileno(imgFile), bodySrc, x * y);
  377.       }
  378.       else
  379.     eprintf(failed_memory, x * y, "picture");
  380.       break;
  381.     default:
  382.       eprintf("unknown picture-type\n");
  383.       break;
  384.   }
  385.  
  386.   return bodySrc;
  387. }
  388.  
  389. struct palpic *GetImage(FILE * file, char *picName, short int alignX, short int alignY) {
  390.   struct palpic *Picture = 0;
  391.   struct rgb *bodySrc;
  392.   struct drgb *bodyTmp;
  393.   short int width, height;
  394.   filetype picType = TYPE_NONE;
  395.  
  396.   if (smoothing)
  397.     switch (S_SCALE) {
  398.       case  1: S_SHIFT =  0; break;
  399.       case  2: S_SHIFT =  1; break;
  400.       case  4: S_SHIFT =  2; break;
  401.       case  8: S_SHIFT =  3; break;
  402.       case 16: S_SHIFT =  4; break;
  403.       default: S_SHIFT = -1; break;
  404.     }
  405.  
  406.   if ((picType = CheckImage(file)) != TYPE_NONE) {
  407.     if ((bodySrc = LoadImage(file, &picType, &width, &height))) {
  408.       short int newwidth = width, newheight = height;
  409.  
  410. #ifdef    DEBUG
  411.       FILE *dumpFile = __fopen("dump", F_WRITE_BINARY);
  412.       fprintf(dumpFile, "P6\n%d %d\n255\n", width, height);
  413.       fflush(dumpFile);
  414.       __write(fileno(dumpFile), bodySrc, (width * height * 3));
  415.       fclose(dumpFile);
  416. #endif
  417.  
  418.       /* calculate a new size that is multiple of align or an absolute value */
  419.       if (alignX > 0) {
  420.     if ((width % alignX))
  421.       newwidth = width - (width % alignX) + alignX;
  422.       }
  423.       else
  424.     newwidth = -alignX;
  425.       if (alignY > 0) {
  426.     if ((height % alignY))
  427.       newheight = height - (height % alignY) + alignY;
  428.       }
  429.       else
  430.     newheight = -alignY;
  431.  
  432.       if ((!dither) || ((dither) && (bodyTmp = (struct drgb *)tmalloc(newwidth * newheight * 3 * sizeof(PRECISION))))) {
  433.     if ((Picture = pmalloc(newwidth, newheight, 0, picName))) {
  434.       double dx = (double)width / newwidth;
  435.       double dy = (double)height / newheight;
  436.       double x, y;
  437.       short int nx, ny;
  438.       struct rgb *Palette = Picture->palette;
  439.       unsigned char *flowDst = Picture->rawdata;
  440.       struct drgb *flowTmp = bodyTmp;
  441.  
  442. #ifdef DEBUG
  443.       mprintf("size; %dx%d, newsize: %dx%d, diffs: %fx%f, type: %d\n", width, height, newwidth, newheight, dx, dy, picType);
  444. #endif
  445.       /* scale body in advance of dithering */
  446.       for (ny = 0, y = 0; ny < newheight; ny++, y += dy) {
  447.         for (nx = 0, x = 0; nx < newwidth; nx++, x += dx) {
  448.           struct rgb rawpix;
  449.  
  450. #define    floatPos(yy, xx)    (((int)(yy) * width) + (int)xx)
  451.  
  452.           /* get unscaled value */
  453.           if (picType == TYPE_PPM) {
  454.         /* colored ppm */
  455.         rawpix = bodySrc[floatPos(y, x)];
  456.  
  457.         if (smoothing) {
  458.           short int sR = 0, sG = 0, sB = 0, sS = 0;
  459.  
  460. #define AddRGB(pospos) {                    \
  461.   struct rgb *addpix = &bodySrc[pospos];            \
  462.   sR += (short int)addpix->r;                    \
  463.   sG += (short int)addpix->g;                    \
  464.   sB += (short int)addpix->b;                    \
  465.   sS++; }
  466.  
  467.           /*
  468.            * smoothing means
  469.            * 123
  470.            * 4a5 a += ((a-((1+2+3+4+5+6+7+8)/8))/smoothing)
  471.            * 678
  472.            */
  473.           if ((y - 1) > 0) {
  474.             if ((x - 1) > 0)
  475.               AddRGB(floatPos(y - 1, x - 1));        /*2 */
  476.             AddRGB(floatPos(y - 1, x));            /*1 */
  477.             if ((x + 1) < width)
  478.               AddRGB(floatPos(y - 1, x + 1));        /*3 */
  479.           }
  480.           if ((x - 1) > 0)
  481.             AddRGB(floatPos(y, x - 1));            /*4 */
  482.           AddRGB(floatPos(y, x));            /*a */
  483.           if ((x + 1) < width)
  484.             AddRGB(floatPos(y, x + 1));            /*5 */
  485.           if ((y + 1) < height) {
  486.             if ((x - 1) > 0)
  487.               AddRGB(floatPos(y + 1, x - 1));        /*7 */
  488.             AddRGB(floatPos(y + 1, x));            /*6 */
  489.             if ((x + 1) < width)
  490.               AddRGB(floatPos(y + 1, x + 1));        /*8 */
  491.           }
  492.  
  493.           sR /= sS;
  494.           sG /= sS;
  495.           sB /= sS;
  496.  
  497. #define SetRGB(src, dst) {                    \
  498.   src -= (short int)rawpix.dst;                    \
  499.   src = S_SHIFT >= 0 ? (src >> S_SHIFT) : (src / S_SCALE);    \
  500.   if(src) {                            \
  501.     src += (short int)rawpix.dst;                \
  502.     if(src > 255)                        \
  503.       src = 255;                        \
  504.     else if(src < 0)                        \
  505.       src = 0;                            \
  506.     rawpix.dst = (unsigned char)src; } }
  507.  
  508.           SetRGB(sR, r);
  509.           SetRGB(sG, g);
  510.           SetRGB(sB, b);
  511.         }
  512.           }
  513.           else if (picType == TYPE_PGM) {
  514.         /* gray    pgm */
  515.         rawpix.r = ((unsigned char *)bodySrc)[floatPos(y, x)];
  516.  
  517.         if (smoothing) {
  518.           short int sG = 0, sS = 0;
  519.  
  520. #define AddGrey(pospos) {                    \
  521.   sG += (short int)(((unsigned char *)bodySrc)[pospos]);    \
  522.   sS++; }
  523.  
  524.           /*
  525.            * smoothing means
  526.            * 123
  527.            * 4a5 a += ((a-((1+2+3+4+5+6+7+8)/8))/smoothing)
  528.            * 678
  529.            */
  530.           if ((y - 1) > 0) {
  531.             if ((x - 1) > 0)
  532.               AddGrey(floatPos(y - 1, x - 1));        /*2 */
  533.             AddGrey(floatPos(y - 1, x));        /*1 */
  534.             if ((x + 1) < width)
  535.               AddGrey(floatPos(y - 1, x + 1));        /*3 */
  536.           }
  537.           if ((x - 1) > 0)
  538.             AddGrey(floatPos(y, x - 1));        /*4 */
  539.           AddGrey(floatPos(y, x));            /*a */
  540.           if ((x + 1) < width)
  541.             AddGrey(floatPos(y, x + 1));        /*5 */
  542.           if ((y + 1) < height) {
  543.             if ((x - 1) > 0)
  544.               AddGrey(floatPos(y + 1, x - 1));        /*7 */
  545.             AddGrey(floatPos(y + 1, x));        /*6 */
  546.             if ((x + 1) < width)
  547.               AddGrey(floatPos(y + 1, x + 1));        /*8 */
  548.           }
  549.  
  550.           sG /= sS;
  551.  
  552. #define SetGrey(src, dst) {                    \
  553.   src -= (short int)rawpix.dst;                    \
  554.   src = S_SHIFT >= 0 ? (src >> S_SHIFT) : (src / S_SCALE);    \
  555.   if(src) {                            \
  556.     src += (short int)rawpix.dst;                \
  557.     if(src > 255)                        \
  558.       src = 255;                        \
  559.     else if(src < 0)                        \
  560.       src = 0;                            \
  561.     rawpix.dst = (unsigned char)src; }}
  562.  
  563.           SetGrey(sG, r);
  564.         }
  565.  
  566.         rawpix.b = rawpix.g = rawpix.r;
  567.           }
  568.  
  569.           if (dither) {
  570.         /* put scaled value */
  571.         *((PRECISION *) flowTmp)++ = (PRECISION) rawpix.r;
  572.         *((PRECISION *) flowTmp)++ = (PRECISION) rawpix.g;
  573.         *((PRECISION *) flowTmp)++ = (PRECISION) rawpix.b;
  574.           }
  575.           else {
  576.         /* put scaled value */
  577.         *flowDst++ = Match(&rawpix, Palette);
  578. #ifdef DEBUG
  579.         mprintf("pixel %dx%d: %02x%02x%02x matches %02x (%02x%02x%02x) with match %d\n", ny, nx, rawpix.r, rawpix.g, rawpix.b, palpix, Palette[palpix].r, Palette[palpix].g, Palette[palpix].b, match);
  580. #endif
  581.           }
  582.         }
  583.         mprogress((int)newheight, (int)ny + 1);
  584.       }
  585.  
  586.       if (dither) {
  587.         flowTmp = bodyTmp;
  588.         for (ny = 0; ny < newheight; ny++) {
  589.           for (nx = 0; nx < newwidth; nx++) {
  590.         unsigned char palpix = *flowDst++ = MatchD(flowTmp, Palette);
  591.         PRECISION_EXT fR, fG, fB;
  592.  
  593. #define MakeError(offset, errorR, errorG, errorB) {        \
  594.   PRECISION_EXT new;                        \
  595.   new = (PRECISION_EXT)(flowTmp[offset].r) + (errorR);        \
  596.   if(new > 255)                            \
  597.     new = 255;                            \
  598.   else if(new < 0)                        \
  599.     new = 0;                            \
  600.   flowTmp[offset].r = (PRECISION)new;                 \
  601.   new = (PRECISION_EXT)(flowTmp[offset].g) + (errorG);        \
  602.   if(new > 255)                            \
  603.     new = 255;                            \
  604.   else if(new < 0)                        \
  605.     new = 0;                            \
  606.   flowTmp[offset].g = (PRECISION)new;                \
  607.   new = (PRECISION_EXT)(flowTmp[offset].b) + (errorB);        \
  608.   if(new > 255)                            \
  609.     new = 255;                            \
  610.   else if(new < 0)                        \
  611.     new = 0;                            \
  612.   flowTmp[offset].b = (PRECISION)new; }
  613.  
  614.         /*
  615.          * calculate error *
  616.          *      erro,7/16
  617.          * 3/16,5/16,1/16
  618.          */
  619.         fR = ((PRECISION_EXT) (Palette[(short int)palpix].r) - (PRECISION_EXT) (flowTmp->r)) / FS_SCALE;
  620.         fG = ((PRECISION_EXT) (Palette[(short int)palpix].g) - (PRECISION_EXT) (flowTmp->g)) / FS_SCALE;
  621.         fB = ((PRECISION_EXT) (Palette[(short int)palpix].b) - (PRECISION_EXT) (flowTmp->b)) / FS_SCALE;
  622.         if ((fR + fG + fB) != 0) {
  623.           if ((ny + 1) < newheight) {
  624.             if ((nx - 1) > 0) {
  625.               MakeError((newwidth - 1), (fR * 3), (fG * 3), (fB * 3));
  626.             }
  627.             MakeError((newwidth), (fR * 5), (fG * 5), (fB * 5));
  628.             if ((nx + 1) < newwidth) {
  629.               MakeError((newwidth + 1), (fR), (fG), (fB));
  630.             }
  631.           }
  632.           if ((nx + 1) < newwidth) {
  633.             MakeError((1), (fR * 7), (fG * 7), (fB * 7));
  634.           }
  635.         }
  636.  
  637.         flowTmp++;
  638.           }
  639.           mprogress((int)newheight, (int)ny + 1);
  640.         }
  641.       }
  642.     }
  643.  
  644.     if (dither)
  645.       tfree(bodyTmp);
  646.       }
  647.       else
  648.     eprintf(failed_memory, picType == TYPE_PPM ? newwidth * newheight * 3 : newwidth * newheight, "picture");
  649.  
  650.       tfree(bodySrc);
  651.     }
  652.     else
  653.       eprintf(failed_memory, picType == TYPE_PPM ? width * height * 3 : width * height, "picture");
  654.   }
  655.   else
  656.     eprintf("unknown picture-type\n");
  657.  
  658.   return Picture;
  659. }
  660.